import os
import sys
from datetime import datetime


def cur_time_str() -> str:
    return datetime.now().strftime("%Y-%m-%d %H-%M-%S")


class LogServer:
    def __init__(self,
                 log_leaf_path: str = "default",
                 log_root_path: str = "",
                 log_file_size: int = 1024 * 1024,
                 log_file_cnt: int = 4):
        """
        日志服务，写到文件中
        :param log_leaf_path: 日志叶子路径
        :param log_root_path: 日志根路径
        :param log_file_size: 日志单个文件大小
        :param log_file_cnt:  日志总文件个数
        """
        if log_root_path == "":
            log_root_path = os.path.join(os.path.dirname(__file__), 'net_log')
        self.cfg_log_path = os.path.join(log_root_path, log_leaf_path)
        self.cfg_log_file_size = log_file_size
        self.cfg_log_file_cnt = log_file_cnt
        self.log_file_no = 0

        os.makedirs(self.cfg_log_path, exist_ok=True)

        newest_mtime = 0
        newest_no = 0
        newest_file = ''
        newest_file_size = 0
        for file in os.listdir(self.cfg_log_path):
            if file.endswith(".txt"):
                file_path = os.path.join(self.cfg_log_path, file)
                pieces = file.split("_")
                if len(pieces) < 2:
                    os.remove(file_path)
                    continue
                try:
                    file_no = int(pieces[0])
                    if file_no >= self.cfg_log_file_cnt:
                        os.remove(file_path)
                        continue
                except ValueError:
                    os.remove(file_path)
                    continue
                mtime = os.path.getmtime(file_path)
                if mtime >= newest_mtime:
                    newest_mtime = mtime
                    newest_no = file_no
                    newest_file = file
                    newest_file_size = os.path.getsize(file_path)
        if newest_file == '':
            self.file = open(os.path.join(self.cfg_log_path, f'0_{cur_time_str()}.txt'), mode='w')
            self.log_file_no = 0
            self.pos = 0
        elif newest_file_size > self.cfg_log_file_size * 0.8:
            if newest_no >= self.cfg_log_file_cnt - 1:
                file_no = 0
            else:
                file_no = newest_no + 1
            self._try_del_old_file()
            self.file = open(os.path.join(self.cfg_log_path, f'{file_no}_{cur_time_str()}.txt'), mode='w')
            self.log_file_no = file_no
            self.pos = 0
        else:
            self.file = open(os.path.join(self.cfg_log_path, newest_file), mode='a')
            self.log_file_no = newest_no
            self.pos = newest_file_size

    def __del__(self):
        self.file.close()
        if sys.platform != "win32":
            os.sync()
        pass

    def _try_del_old_file(self):
        for file in os.listdir(self.cfg_log_path):
            if file.endswith(".txt"):
                file_path = os.path.join(self.cfg_log_path, file)
                pieces = file.split("_")
                if len(pieces) >= 2:
                    try:
                        file_no = int(pieces[0])
                    except ValueError:
                        pass
                    else:
                        if file_no == self.log_file_no:
                            os.remove(file_path)

    def _switch_file(self):
        if self.file:
            self.file.close()
            del self.file
            if self.log_file_no >= self.cfg_log_file_cnt - 1:
                self.log_file_no = 0
            else:
                self.log_file_no += 1
            self._try_del_old_file()
            self.file = open(os.path.join(self.cfg_log_path, f'{self.log_file_no}_{cur_time_str()}.txt'), mode='w')
            self.pos = 0

    def write(self, *args, sep=' ', end='\n'):
        if self.file:
            write_str = sep.join(f"{arg}" for arg in args) + end
            self.file.write(write_str)
            self.file.flush()
            self.pos += len(write_str)
            if self.pos >= self.cfg_log_file_size:
                self._switch_file()
        pass
